package cn.genmer.test.security.leetcode.medium;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

/**
 * 1609. 奇偶树(中等)
 * 如果一棵二叉树满足下述几个条件，则可以称为 奇偶树 ：
 *
 * 二叉树根节点所在层下标为 0 ，根的子节点所在层下标为 1 ，根的孙节点所在层下标为 2 ，依此类推。
 * 偶数下标 层上的所有节点的值都是 奇 整数，从左到右按顺序 严格递增
 * 奇数下标 层上的所有节点的值都是 偶 整数，从左到右按顺序 严格递减
 * 给你二叉树的根节点，如果二叉树为 奇偶树 ，则返回 true ，否则返回 false 。
 *
 *
 *
 * 示例 1：
 *
 *
 *
 * 输入：root = [1,10,4,3,null,7,9,12,8,6,null,null,2]
 * 输出：true
 * 解释：每一层的节点值分别是：
 * 0 层：[1]
 * 1 层：[10,4]
 * 2 层：[3,7,9]
 * 3 层：[12,8,6,2]
 * 由于 0 层和 2 层上的节点值都是奇数且严格递增，而 1 层和 3 层上的节点值都是偶数且严格递减，因此这是一棵奇偶树。
 * 示例 2：
 *
 *
 *
 * 输入：root = [5,4,2,3,3,7]
 * 输出：false
 * 解释：每一层的节点值分别是：
 * 0 层：[5]
 * 1 层：[4,2]
 * 2 层：[3,3,7]
 * 2 层上的节点值不满足严格递增的条件，所以这不是一棵奇偶树。
 * 示例 3：
 *
 *
 *
 * 输入：root = [5,9,1,3,5,7]
 * 输出：false
 * 解释：1 层上的节点值应为偶数。
 * 示例 4：
 *
 * 输入：root = [1]
 * 输出：true
 * 示例 5：
 *
 * 输入：root = [11,8,6,1,3,9,11,30,20,18,16,12,10,4,2,17]
 * 输出：true
 *
 *
 * 提示：
 *
 * 树中节点数在范围 [1, 105] 内
 * 1 <= Node.val <= 106
 */
public class ParityTree {
      static class TreeNode {
       int val;
       TreeNode left;
       TreeNode right;
       TreeNode() {}
       TreeNode(int val) { this.val = val; }
       TreeNode(int val, TreeNode left, TreeNode right) {
           this.val = val;
           this.left = left;
           this.right = right;
       }
   }

    public static void main(String[] args) {
        ParityTree parityTree = new ParityTree();
//        boolean evenOddTree2 = parityTree.isEvenOddTree2(new TreeNode(5, new TreeNode(4, new TreeNode(3, null, null), new TreeNode(3, null, null)), new TreeNode(2, new TreeNode(7, null, null), null)));
        boolean evenOddTree2 = parityTree.isEvenOddTree2(null);
        System.out.println(evenOddTree2);
    }

    /**
     * BFS - 广度优先搜索
     * @param root
     * @return
     */
    public static boolean isEvenOddTree(TreeNode root) {
        Deque<TreeNode> d = new ArrayDeque<>();
        boolean flag = true;
        d.addLast(root);
        while (!d.isEmpty()) {
            int size = d.size(), prev = flag ? 0 : 0x3f3f3f3f;
            while (size-- > 0) {
                TreeNode node = d.pollFirst();
                int cur = node.val;
                if (flag && (cur % 2 == 0 || cur <= prev)) return false;
                if (!flag && (cur % 2 != 0 || cur >= prev)) return false;
                prev = cur;
                if (node.left != null) d.addLast(node.left);
                if (node.right != null) d.addLast(node.right);
            }
            flag = !flag;
        }
        return true;
    }

    /**
     * DFS - 深度度优先搜索
     * @param root
     * @return
     */
    Map<Integer, Integer> map = new HashMap<>();
    public boolean isEvenOddTree2(TreeNode root) {
        if (root != null)
        return dfs(root, 0);
        return false;
    }
    boolean dfs(TreeNode root, int idx) {
        boolean flag = idx%2 == 0;
        int prev = map.getOrDefault(idx, flag ? 0 : 0x3f), cur = root.val;
        if (flag && (idx %2 == 0 || cur <= prev)) return false;
        if (!flag && (idx %2 != 0 || cur >= prev)) return false;

        map.put(idx, root.val);
        if (root.left != null && !dfs(root.left, idx+1)) return false;
        if (root.right != null && !dfs(root.right, idx+1)) return false;
        return true;
    }

    /**
     * 是否奇数
     * @param val
     * @return
     */
    private static boolean isOdd(int val){
          if (val % 2 == 0){
              return false;
          } else {
              return true;
          }
    }
}
